﻿#define ETLCONSOL

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Security.Cryptography;
using EtlComm;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Xml.Linq;
using System.Collections;
using System.Configuration;


namespace EtlMonitor
{
    public partial class frmMain : Form
    {
        [DllImport("user32.dll", SetLastError = true,EntryPoint="FindWindowW")]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", SetLastError = true)]
        static extern int CloseWindow(IntPtr hWnd);

        public frmMain()
        {
            InitializeComponent();
        }
        //EtlConsol
        //#32770
        TimeSpan[] tsCounts = new TimeSpan[10];
        uint timeCounts = 0;
        uint tsIndex = 0;

        uint RestStart = 0;
        uint RestEnd = 1;

        XElement _XEStation = null;
        //更新数据对列
        Queue<UpdateData> queUpdateData = new Queue<UpdateData>();
        //服务端线程数
        int numThreads = 250;

        volatile static int calls = 0;


        private void frmMain_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                notifyIcon1.Visible = true;
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Process etlProcess = null;
            Process[] p = Process.GetProcessesByName("EtlConsol");
            Debug.WriteLine(string.Format("DateTime.Now.Hour={0}",DateTime.Now.Hour));
            if (p.Count() != 0)
            {
                var difTime = DateTime.Now - p[0].StartTime;
                if (difTime.TotalHours > 24)
                {
                    try
                    {
                        p[0].Kill();
                    }
                    catch (System.Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    }
                    
                }
            }
            
            //早上3点-4点，重启抽取程序
            if ((DateTime.Now.Hour >= RestStart) && (DateTime.Now.Hour <= RestEnd))
            {
                if (p.Count() > 0)
                    foreach (var proc in p)
                        try
                        {
                            proc.Kill();
                        }
                        catch (System.Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                        }
                        
				Debug.WriteLine("抽取进程重启中...");                
                return;
            }
            if (p.Count() == 0)
            {
                //timer_bakup_Tick(null, null);
                Debug.WriteLine("Etlconsol重启中...");
                ProcessStartInfo psi = new ProcessStartInfo("etlconsol");
                psi.Arguments = "96e65773803e47ee1001b05a99965d76";
#if TRIAL
                if (DateTime.Now >= new DateTime(2013,7,1))
                {
                    psi.Arguments = "96e65773803e47ee1001b05c99965d76";
                }
         
#endif
                etlProcess = Process.Start(psi);
            }
            else
            {
                etlProcess = p[0];
            }
            IntPtr hWnd = FindWindow("#32770", "EtlConsol");
            if (hWnd != IntPtr.Zero)
            {
                etlProcess.Kill();
                CloseWindow(hWnd);
            }
            return;
            //tsslprocess.Text = etlproc.TotalProcessorTime.ToString();
            //if (timeCounts++ % 60 == 0)
            //{
            //    tsCounts[tsIndex % 10] = etlProcess.TotalProcessorTime;
            //    if (tsIndex % 10 == 9)
            //    {
            //        var dTick = (tsCounts.Max(x=>x.Ticks) - tsCounts.Min(x=>x.Ticks)) / 600;
            //        if (dTick < 50000)
            //        {
            //            etlProcess.Kill();
            //        }
            //        tsslprocess.Text = dTick.ToString();
            //    }
            //    tsIndex++;
            //}
        }

        private void button1_Click(object sender, EventArgs e)
        {
            RestStart = uint.Parse(ConfigurationManager.AppSettings["RestStart"].ToString());
            RestEnd = uint.Parse(ConfigurationManager.AppSettings["RestEnd"].ToString()); ;

            timer_Killer.Start();
            //timer_bakup.Start();
            timer_SaveXML.Start();
            //if (!backgroundWorker1.IsBusy)
            //{
            //    backgroundWorker1.RunWorkerAsync("ChinaPetroEtlService");
            //}
            pictureBox1.Image = global::EtlMonitor.Properties.Resources._008ah;
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                if (backgroundWorker1.CancellationPending)
                    break;
                ServiceStart(e.Argument.ToString());

                WaitForStop(e.Argument.ToString());
            }
        }

        private void WaitForStop(string serviceName)
        {
            if (!ServiceIsExisted(serviceName))
            {
                MessageBox.Show(string.Format("{0} 还没有安装.", serviceName), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            try
            {
                ServiceController service = new ServiceController(serviceName);
                service.WaitForStatus(ServiceControllerStatus.Stopped);
            }
            catch { }
        }

        public bool ServiceStart(string serviceName)
        {
            if (!ServiceIsExisted(serviceName))
            {
                MessageBox.Show(string.Format("{0} 还没有安装.", serviceName), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            try
            {
                ServiceController service = new ServiceController(serviceName);
                if (service.Status == ServiceControllerStatus.Running)
                {
                    return true;
                }
                else
                {
                    TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 60);
                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running, timeout);
                }
            }
            catch
            {
                return false;
            }
            return true;
        }

        //判断window服务是否存在：
        private bool ServiceIsExisted(string serviceName)
        {  
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController s in services)
            {
                if (s.ServiceName == serviceName)
                {
                    return true;
                }
            }
            return false;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            timer_Killer.Stop();
            //timer_bakup.Stop();
            timer_SaveXML.Stop();
            //backgroundWorker1.CancelAsync();
            pictureBox1.Image = global::EtlMonitor.Properties.Resources._008ah1;

            Process[] proc = Process.GetProcessesByName("EtlConsol");
            if (proc.Count()>0)
                foreach (var p in proc)
                    p.Kill();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
        }

        private void menuItemExit_Click(object sender, EventArgs e)
        {
            MessageBox.Show("运行期间不能退出应用程序...","提示",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            notifyIcon1.Visible = false;
        }

        void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            _XEStation = XElement.Load(EtlGlobal.XmlStationFile);
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
            //timer_bakup.Interval = 1000 * 60 * 60 * 12;
            timer_SaveXML.Interval = 1000 * 60;
            timer_Killer.Interval = 1000 * 10;
            RunServerThread();
        }

        //备份XML文件
        private void timer_bakup_Tick(object sender, EventArgs e)
        {
            string[] files = new string[] { "ColumnsReference.xml", "StationTaskRunInfo.xml", "TaskInfo.xml" };
            string bakDir = "bak";
            //if (Process.GetProcessesByName("etlconsol").Count() == 0)
            //    return;
            try
            {
                foreach (var src in files)
                {
                    string dstFileNmae = DateTime.Now.ToString("yyyy-MM-dd-HH-mm.") + src;
                    if (!Directory.Exists(bakDir))
                        Directory.CreateDirectory(bakDir);
                    FileInfo fi = new FileInfo(src);
                    if (fi.Length < 500 * 1024)
                        continue;
                    File.Copy(src, bakDir + "\\" + dstFileNmae);
                }

                string[] bakFiles = Directory.GetFiles(bakDir);
                foreach (var del in bakFiles)
                {
                    string dat = DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd");
                    if (del.Contains(dat))
                    {
                        File.Delete(del);
                    }
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
        /// <summary>
        /// 服务线程，接收XML产更新数据
        /// </summary>
        /// <param name="data"></param>
        private void ServerThread(object data)
        {
            while (true)
            {
                try
                {
                    using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("sunjunwu", PipeDirection.InOut, 253))
                    {
                        int threadId = Thread.CurrentThread.ManagedThreadId;
                        pipeServer.WaitForConnection();

                        EtlStreamString ss = new EtlStreamString(pipeServer);
                        ss.WriteString("SERVER READY");
                        //"SJW|StationID|TaskID|BeginParam|EndParam|ExeTime"
                        string content = ss.ReadString();
                        UpdateData ud = GetUpdateData(content);
                        if (ud != null)
                        {
                            lock (queUpdateData)
                            {
#if TRAIL
                                if (DateTime.Now >= new DateTime(2013, 4, 1))
                                {
                                    continue;
                                }
#endif
                                queUpdateData.Enqueue(ud);
                                Debug.WriteLine("收到数据 :" + (calls++).ToString() + content);
                            }
                        }
                        pipeServer.Close();
                    }
                }
                catch (IOException e)
                {
                    Console.WriteLine("ERROR: {0}", e.Message);
                }
            }
        }

        private void RunServerThread()
        {
            Thread[] servers = new Thread[numThreads];
            for (int i = 0; i < numThreads; i++)
            {
                servers[i] = new Thread(ServerThread);
                servers[i].Start();
            }
        }

        /// <summary>
        /// q解析更新数据
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        private UpdateData GetUpdateData(string content)
        {
            string[] udArray = content.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            if (udArray.Length != 6)
            {
                Debug.WriteLine("收到空的更新数据...");
                return null;
            }
            if (!udArray[0].Equals("SJW"))
            {
                Debug.WriteLine("收到非法的更新数据...");
                return null;
            }
            return new UpdateData
            {
                StationID = udArray[1],
                TaskID = udArray[2],
                BeginParam = udArray[3],
                EndParam = udArray[4],
                ExeTime = udArray[5]
            };
        }

        private void timer_SaveXML_Tick(object sender, EventArgs e)
        {
            Debug.WriteLine("开始保存数据...");
            try
            {
                bool isSave = false;
                lock (queUpdateData)
                {
                    Debug.Assert(_XEStation != null);
                    while (queUpdateData.Count != 0)
                    {
                        UpdateData ud = queUpdateData.Dequeue();
                        Debug.Assert(ud != null);
                        try
                        {
                            var record = (from a in _XEStation.Descendants("Station")
                                          where a.Element("StationID").Value == ud.StationID
                                          select a).FirstOrDefault();
                            if (record != null)
                            {
                                var element = (from a in record.Descendants("TaskInfo")
                                               where a.Element("TaskID").Value == ud.TaskID
                                               select a).FirstOrDefault();
                                if (element != null)
                                {
                                    element.SetElementValue("StartTime", ud.BeginParam);
                                    element.SetElementValue("EndTime", ud.EndParam);
                                    isSave = true;
                                }
                            }
                        }
                        catch (System.Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                            continue;
                        }
                        
                    }
                    if (isSave)
                    {
                        _XEStation.Save(EtlGlobal.XmlStationFile);
                        Debug.WriteLine("保存数据到 " + EtlGlobal.XmlStationFile);
                    }
                }
            }
            catch (Exception ec)
            {
                Debug.WriteLine(ec.ToString());
            }
        }
    }
}
